/*
用法	含义
PropTypes.array	数组
PropTypes.bool	布尔类型
PropTypes.func	函数
PropTypes.number	数字
PropTypes.object	对象
PropTypes.string	字符串
PropTypes.symbol	Symbol
PropTypes.node	任何可被渲染的元素(包括数字、字符串、元素或数组)
PropTypes.element	一个 React 元素
PropTypes.instanceOf(Message)	Message类的实例
PropTypes.oneOf(['News', 'Photos'])	枚举类型
PropTypes.oneOfType([PropTypes.string,PropTypes.number,PropTypes.instanceOf(Message)])	几种类型中的任意一个类型
PropTypes.arrayOf(PropTypes.number)	一个数组由某一类型的元素组成
PropTypes.objectOf(PropTypes.number)	可以指定一个对象由某一类型的值组成
PropTypes.shape({color: PropTypes.string,fontSize: PropTypes.number})	可以指定一个对象由特定的类型值组成
PropTypes.func.isRequired	你可以在任何 PropTypes 属性后面加上 isRequired ，确保这个 prop 没有被提供时，会打印警告信息
PropTypes.any.isRequired	任意类型的数据
customProp: function(props, propName, componentName){}	你可以指定一个自定义验证器。它在验证失败时应返回一个 Error 对象
*/
import React from 'react';
import ReactDOM from 'react-dom';
import PropTypes from 'prop-types';

const root: HTMLElement | null = document.getElementById('root');

interface PersonProps {
    name?: string;
    age?: number;
    gender?: 'male' | 'female';
    hobby?: Array<string>;
    position?: { x: number, y: number; };

    [propName: string]: any;
}

class Person extends React.Component<PersonProps>{
  static defaultProps: PersonProps = {
    name:'ahhh'
  };

  static propTypes = {
    name: PropTypes.string.isRequired
    , gender: PropTypes.oneOf(['male', 'female']).isRequired
    , hobby: PropTypes.arrayOf(PropTypes.string)
    , position: PropTypes.shape({
      x: PropTypes.number
      ,y: PropTypes.number
    })
    // 自定义校验器 校验年龄age必须>0并且小于100岁
    , age(props: PersonProps, propName: string, componentName: string) {
      let age = props[propName];  //要在PersonProps中声明 [propName: string]: any 不然报错
      if (age < 0 || age > 100) {
        return new Error(`Invalid Prop ${propName} supplied to ${componentName}`);
      }
      return null;
    }
  };

  render(): React.ReactNode {
    const {name, gender, age, hobby, position={}} = this.props;
    return <div>
      <p>name:{name}</p>
      <p>gender:{gender}</p>
      <p>age:{age}</p>
      <p>hobby:{hobby}</p>
      <p>position:{position.toString()}</p>
    </div>;
  }
}

let personProps: PersonProps = {
  gender: 'male'
  ,age:111
  , hobby: ['football', 'basketball']
  , position: {x:100, y: 100}
};

ReactDOM.render(<Person {...personProps}/>, root);
